﻿
#pragma once

#include "fstream"
#include <string>

namespace tools
{
    struct Generator
    {
        typedef ::std::string Str;
        typedef const size_t Val;

        enum eTARGET { eBUTTON, eIMAGE };

        Generator(const Str& nameImagesetFile, const Str& path2ImageFile,const Str& nameImageset, const eTARGET target)
            :mPath2ImageFile(path2ImageFile)
            ,mNameImagesetFile(nameImagesetFile)
            ,mNameImageset(nameImageset)
            ,m1(true)
            ,m3(false)
            ,m9(false)
            ,mTarget(target)
        {}

        Str Begin()const
        {
            const Str autoScaled = "<Imageset autoScaled=\"\" ";
            const Str imagefile = "imagefile=\"" + mPath2ImageFile+"\" ";
            const Str name = "name=\""+mNameImageset+"\" ";
            const Str resolution = "nativeHorzRes=\"800\" nativeVertRes=\"600\" ";
            const Str version = "version=\"2\">";

            return autoScaled + imagefile + name + resolution + version;
        }
        Str Ended()const { return "</Imageset>"; }

        Str Record(const Str& name, Val _w, Val _h, Val _x, Val _y)const
        {
            const Str h = ::std::to_string(_h);
            const Str w = ::std::to_string(_w);
            const Str x = ::std::to_string(_x);
            const Str y = ::std::to_string(_y);

            return "    <Image height=\"" + h + "\" name=\"" + name + "\" width=\"" +
                w + "\" xPos=\"" + x + "\" yPos=\"" + y + "\"/>";
        }

        static const Str& FrameName(const size_t n, const eTARGET target)
        {
            const static Str s[]={"Normal","Hover","Pressed","Focus","Disaabled","Unkown"};
            const static Str substrate = "Substrate";

            if(target == eIMAGE)
                return substrate;

            return (n>6)? s[6] : s[n];
        }
        
        Str Proccess1()const 
        {
            Str re; Val w = mW/mFrame; Val h = mH;
            for(size_t n=0;n<mFrame;++n)
                re += Record("1"+ FrameName(n,mTarget), w,h, n*w, 0)+"\n"; 
            return re;
        }
        Str Proccess3()const 
        {
            Str re; Val w = mW/mFrame; Val h = mH; Val cw  = mCornerW; 
            for(size_t n=0;n<mFrame;++n)
            {
                re += Record("3"+ FrameName(n,mTarget)+"L", cw,      h,  n*w,          0)+"\n"; 
                re += Record("3"+ FrameName(n,mTarget)+"M", w-2*cw,  h,  n*w+cw,       0)+"\n"; 
                re += Record("3"+ FrameName(n,mTarget)+"R", cw,      h,  (n+1)*w - cw, 0)+"\n"; 
            }
            return re;
         }

        Str Proccess9()const 
        {
            Str re; Val w = mW/mFrame; Val h = mH; Val cw  = mCornerW;  Val ch  = mCornerH; 
            for(size_t n=0;n<mFrame;++n)
            {
                re += Record("9"+ FrameName(n,mTarget)+"LU", cw, ch,     n*w, 0)    +"\n"; 
                re += Record("9"+ FrameName(n,mTarget)+"L",  cw, h-2*ch, n*w, ch)   +"\n"; 
                re += Record("9"+ FrameName(n,mTarget)+"LD", cw, ch,     n*w, h-ch) +"\n"; 
                
                re += Record("9"+ FrameName(n,mTarget)+"MU", w-2*cw, ch,     n*w+cw, 0)    +"\n"; 
                re += Record("9"+ FrameName(n,mTarget)+"M",  w-2*cw, h-2*ch, n*w+cw, ch)   +"\n"; 
                re += Record("9"+ FrameName(n,mTarget)+"MD", w-2*cw, ch,     n*w+cw, h-ch) +"\n"; 

                re += Record("9"+ FrameName(n,mTarget)+"RU", cw, ch,     (n+1)*w - cw, 0)   +"\n"; 
                re += Record("9"+ FrameName(n,mTarget)+"R",  cw, h-2*ch, (n+1)*w - cw, ch)  +"\n"; 
                re += Record("9"+ FrameName(n,mTarget)+"RU", cw, ch,     (n+1)*w - cw, h-ch)+"\n"; 
            }
            return re;
        }

        Str Proccess()const
        {
            Str re = Begin()+"\n";
            
            if(m1)
                re += Proccess1();
            if(m3)
                re += Proccess3();
            if(m9)
                re += Proccess9();
            
            re += Ended()+"\n";
            return re;
        }

        void Generate()const
        {
            ::std::fstream f(mNameImagesetFile, ::std::ios::out|::std::ios::trunc);

            if(!f)
                cout<<"error open file: "<< mNameImagesetFile<<endl;
            else
                f << Proccess();
        }

        Str mPath2ImageFile;
        Str mNameImagesetFile;
        Str mNameImageset;
        size_t mW, mH, mCornerW, mCornerH, mFrame;
        bool m1,m3,m9;

        eTARGET mTarget;
        
    };


    

}//namespace tools


